package cn.psvmc.cxzapi.util;

import cn.psvmc.cxzapi.config.AlipayConfig;
import cn.psvmc.cxzapi.config.ConfigKey;
import cn.psvmc.cxzapi.constant.GlobalConstant;
import cn.psvmc.cxzapi.exception.ServiceException;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.parser.Feature;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.internal.util.AlipayEncrypt;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipaySystemOauthTokenRequest;
import com.alipay.api.request.AlipayUserInfoShareRequest;
import com.alipay.api.response.AlipaySystemOauthTokenResponse;
import com.alipay.api.response.AlipayUserInfoShareResponse;
import com.sun.istack.NotNull;
import lombok.extern.slf4j.Slf4j;


import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.DecimalFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @Description 公用工具类
 * @Author ywx
 * @Date 2023/7/24 11:27:10
 **/
@Slf4j
public class ToolUtils {
    //付款状态（1已支付2已退款22部分退款）
    public static final List<Integer> payStatus = Arrays.asList(1, 2, 22);
    //退款状态（2已退款22部分退款）
    public static final List<Integer> refundStatus = Arrays.asList(2, 22);

    //付款状态（1已支付22部分退款）
    public static final List<Integer> payStatusBuyout = Arrays.asList(1, 22);

    /**
     * @Description 字符串是否不为空
     * @Param [obj]
     * @Author ywx
     * @Return boolean
     */
    public static boolean isNotEmpty(Object obj) {
        return null != obj && !obj.toString().trim().isEmpty();
    }

    /**
     * @Description 字符串是否为空
     * @Param [obj]
     * @Author ywx
     * @Return boolean
     */
    public static boolean isEmpty(Object obj) {
        return null == obj || obj.toString().trim().isEmpty() || "null".equals(obj.toString().trim());
    }


    /**
     * 功能描述  integer 是否是有效的类型
     * @Param obj
     * @Return boolean
     * @Author ywx
     * @Date 2019/7/15
     */
    public static boolean isTrueInteger(Integer obj) {
        return null != obj && obj > 0;
    }

    /**
     * @Description Double数值是否有效
     * @Date 2024/9/12 23:02
     * @Author YWX
     * @Param [obj]
     * @Return boolean
     **/
    public static boolean isTrueDoule(Double obj) {
        return Optional.ofNullable(obj)
                .filter(v -> !Double.isNaN(v))
                .filter(v -> v > 0)
                .isPresent();
    }

    /**
     * 去除字符串中前后的全、半角空格
     *
     * @Return java.lang.String
     * @Param [str]
     * @Author ywx
     * @Date 2020/4/1 9:57
     **/
    public static String strTrim(String str) {
        str = str.trim();// 去除字符串前后的半角空格
        while (str.startsWith("　")) {// 去除字符串前的全角空格
            str = str.substring(1).trim();
        }
        while (str.endsWith("　")) {// 去除字符串后的全角空格
            str = str.substring(0, str.length() - 1).trim();
        }
        return str;
    }

    /**
     * 参数校验，为空的话提示定义的提示信息
     *
     * @Return void
     * @Param [strs] strs={"filename","msg","type","filename2","msg2","type2"}
     * @Author ywx
     * @Date 2020/4/26 15:08
     **/
    public static void validation(Object[] strs) {
        for (int i = 0; i < strs.length; i += 3) {
            Object filename = strs[i];
            String msg = strs[i + 1].toString() + "不能为空";
            int type = Integer.parseInt(strs[i + 2].toString());
            if (type == 1) {// Integer类型参数
                if (ToolUtils.isEmpty(filename) || filename.equals(0)) {
                    throw new ServiceException(msg);
                }
            } else if (type == 2) {// String类型参数
                if (ToolUtils.isEmpty(filename)) {
                    throw new ServiceException(msg);
                }
            } else if (type == 3) {// List类型参数
                List list = (List) filename;
                if (!ToolUtils.isListNotEmpty(list)) {
                    throw new ServiceException(msg);
                }
            }
        }
    }

    /**
     * 密码加密
     *
     * @Return java.lang.String
     * @Author ywx
     * @Date 2022/5/20 10:18
     */
    public static String getMD5Pwd(String pwd) {
        if (ToolUtils.isEmpty(pwd)) {
            return null;
        }
        MD5 md5 = new MD5();
        return md5.getMD5ofStr(md5.getMD5ofStr(md5.getMD5ofStr(pwd)));
    }

    /**
     * @Return boolean
     * @Description list不为空
     * @Author ywx
     * @Date 2023/8/10 15:01
     **/
    public static boolean isListNotEmpty(List list) {
        return null != list && !list.isEmpty() && list.get(0) != null;
    }

    /**
     * @Return boolean
     * @Description list为空
     * @Author ywx
     * @Date 2023/8/10 15:01
     **/
    public static boolean isListEmpty(List list) {
        return null == list || list.isEmpty() || list.get(0) == null;
    }

    // 构建树
    public static List<Map<String, Object>> buildTree(List<Map<String, Object>> trees, String id, String pid, String cname) {
        // 获取grouppid为空的根节点
        List<Map<String, Object>> list = trees.stream().filter(item -> ToolUtils.isEmpty(item.get(pid))).collect(Collectors.toList());
        // 根据grouppid进行分组
        Map<String, List<Map<String, Object>>> map = trees.stream().filter(m -> ToolUtils.isNotEmpty(m.get(pid))).collect(Collectors.groupingBy(m -> m.get(pid).toString(),
                                                                                                                                                LinkedHashMap::new,
                                                                                                                                                Collectors.toList()));
        ToolUtils.recursionTree(list, map, id, cname);
        return list;
    }

    // 递归遍历节点
    public static void recursionTree(List<Map<String, Object>> list, Map<String, List<Map<String, Object>>> map, String id, String cname) {
        for (Map<String, Object> treeSelect : list) {
            List<Map<String, Object>> childList = map.get(treeSelect.get(id).toString());
            treeSelect.put(cname, childList);
            if (null != childList && !childList.isEmpty()) {
                ToolUtils.recursionTree(childList, map, id, cname);
            }
        }
    }

    /**
     * 随机生成4位随机码
     *
     * @Return java.lang.Integer
     * @Param []
     * @Author ywx
     * @Date 2020/5/8 9:29
     **/
    public static Integer messageCode() {
        return (int) ((Math.random() * 9 + 1) * 1000);
    }

    /*
     * @Description 验证手机号
     * @Date 2024/3/12 16:12:34
     * @Author ywx
     * @Param [phone]
     * @Return boolean
     **/
    public static boolean checkPhone(String phone) {
        String regex = "^1[3456789]\\d{9}$";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(phone);

        return !matcher.matches();
    }

    /**
     * @Description 对象转数值
     * @Date 2024/4/30 15:27
     * @Author YWX
     * @Param [num]
     * @Return java.lang.Integer
     **/
    public static Integer objToInteger(Object num) {
        if (num == null) {
            return 0;
        }
        return Integer.parseInt(num.toString());
    }

    /**
     * @Description 对象转字符串
     * @Date 2024/5/7 14:31
     * @Author YWX
     * @Param [obj]
     * @Return java.lang.String
     **/
    public static String objToString(Object obj) {
        if (obj == null) {
            return "";
        }
        return obj.toString();
    }

    /**
     * @Description 对象转double
     * @Date 2024/9/3 8:36
     * @Author YWX
     * @Param [obj]
     * @Return java.lang.Double
     **/
    public static Double objToDouble(Object obj) {
        if (obj == null) {
            return 0.0;
        }
        return Double.parseDouble(obj.toString());
    }

    /**
     * @Description 对象转long
     * @Date 2024/9/20 23:31
     * @Author YWX
     * @Param [obj]
     * @Return java.lang.Long
     **/
    public static Long objToLong(Object obj) {
        if (obj == null) {
            return 0L;
        }
        String value = obj.toString();
        if (value.contains(".")) {
            value = value.split("\\.")[0];
        }
        return Long.valueOf(value);
    }

    /**
     * @Description 字符串转日期
     * @Date 2024/9/26 17:33
     * @Author YWX
     * @Param [str]
     * @Return java.time.LocalDateTime
     **/
    public static LocalDateTime strToLocalDateTime(String str) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        // 将字符串转换为LocalDateTime
        return LocalDateTime.parse(str, formatter);
    }

    /**
     * @Description date转LocalDateTime
     * @Date 2024/10/26 21:08
     * @Author YWX
     * @Param [sendPayDate]
     * @Return java.time.LocalDateTime
     **/
    public static LocalDateTime dateToLocalDateTime(Date sendPayDate) {
        return sendPayDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
    }

    /**
     * @Description localDateTime转date
     * @Date 2024/11/15 23:45
     * @Author YWX
     * @Param [localDateTime]
     * @Return java.util.Date
     **/
    public static Date localDateTimeToDate(LocalDateTime localDateTime) {
        // 将LocalDateTime转换为ZonedDateTime，使用系统默认时区
        ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.systemDefault());

        // 获取Instant并转换为Date
        return Date.from(zonedDateTime.toInstant());
    }

    /**
     * @Description 获取token
     * @Date 2024/8/12 21:59
     * @Author YWX
     * @Param []
     * @Return java.lang.String
     **/
    public static String getToken() {
        return AES.encrypt(ToolUtils.getUuid(), ConfigKey.secretKey);//加密
    }

    //获取uuid
    public static String getUuid() {
        return UUID.randomUUID().toString().replace("-", "");
    }

    /**
     * @Description 校验当前登录人id
     * @Date 2024/8/13 16:47
     * @Author YWX
     * @Param [userid]
     * @Return void
     **/
    public static void checkUserId(int userid) {
        if (!ToolUtils.isTrueInteger(userid)) {
            throw new ServiceException("当前登录人id不能为空！");
        }
    }

    /**
     * @Description 获取当前时间指定格式
     * @Date 2024/8/13 23:46
     * @Author YWX
     * @Param [format]
     * @Return java.lang.String
     **/
    public static String getNowDateFormat(String format){
        //格式化
        DateTimeFormatter fmDate = DateTimeFormatter.ofPattern(format);
        //当天
        LocalDateTime today = LocalDateTime.now();
        return today.format(fmDate);
    }

    // 获取n天后的日期并格式化为指定格式
    public static String getDateAfterDays(int n, String format) {
        LocalDateTime currentDate = LocalDateTime.now();
        LocalDateTime dateAfterDays = currentDate.plusDays(n);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);
        return dateAfterDays.format(formatter);
    }

    /**
     * @Description 获取昨天的时间，指定格式
     * @Date 2024/8/13 23:46
     * @Author YWX
     * @Param [format]
     * @Return java.lang.String
     **/
    public static String getYesterdayDateFormat(String format) {
        // 格式化
        DateTimeFormatter fmDate = DateTimeFormatter.ofPattern(format);
        // 昨天
        LocalDateTime yesterday = LocalDateTime.now().minusDays(1);
        return yesterday.format(fmDate);
    }


    /**
     * @Description 两数相除向上取整保留两位小数
     * @Date 2024/8/14 17:39
     * @Author YWX
     * @Param [a, b]
     * @Return java.math.BigDecimal
     **/
    public static double divideAndCeil(Object a, Object b) {
        if (a == null || b == null || b.equals(0)) {
            return 0;
        }
        // 首先将整数转换为 BigDecimal 类型
        BigDecimal numerator = new BigDecimal(a.toString());
        BigDecimal denominator = new BigDecimal(b.toString());

        // 使用 divide() 方法进行除法运算，并指定向上取整的舍入模式 RoundingMode.CEILING
        BigDecimal result = numerator.divide(denominator, 2, RoundingMode.CEILING);

        // 将结果转换为 double 类型返回
        return result.doubleValue();
    }

    /**
     * @Description 两数相除向下取整保留两位小数
     * @Date 2024/9/1 22:16
     * @Author YWX
     * @Param [a, b]
     * @Return double
     **/
    public static double divideAndCeilDown(Double a, Integer b) {
        if (a == null || b == null || b == 0) {
            return 0;
        }
        // 首先将整数转换为 BigDecimal 类型
        BigDecimal numerator = new BigDecimal(a.toString());
        BigDecimal denominator = new BigDecimal(b.toString());

        // 使用 divide() 方法进行除法运算，并指定向下取整的舍入模式 RoundingMode.FLOOR
        BigDecimal result = numerator.divide(denominator, 2, RoundingMode.FLOOR);

        // 将结果转换为 double 类型返回
        return result.doubleValue();
    }

    /**
     * @Description 两数相乘
     * @Date 2024/9/7 18:23
     * @Author YWX
     * @Param [a, b]
     * @Return double
     **/
    public static double multiply(Object a, Object b) {
        if (a == null || b == null) {
            return 0;
        }
        // 首先将整数转换为 BigDecimal 类型
        BigDecimal numerator = new BigDecimal(a.toString());
        BigDecimal denominator = new BigDecimal(b.toString());

        // 使用 multiply() 方法进行乘法运算
        BigDecimal result = numerator.multiply(denominator);

        // 将结果转换为 double 类型返回
        return ToolUtils.formatDouble2(result.doubleValue());
    }

    /**
     * @Description 两数相减
     * @Date 2024/8/15 23:07
     * @Author YWX
     * @Param [a, b]
     * @Return double
     **/
    public static double subtract(Object a, Object b) {
        if (a == null || b == null) {
            return 0;
        }
        // 首先将整数转换为 BigDecimal 类型
        BigDecimal numerator = new BigDecimal(a.toString());
        BigDecimal denominator = new BigDecimal(b.toString());

        // 使用 subtract() 方法进行减法运算
        BigDecimal result = numerator.subtract(denominator);

        // 将结果转换为 double 类型返回
        return result.doubleValue();
    }

    /**
     * @Description 两数相加
     * @Date 2024/8/15 23:10
     * @Author YWX
     * @Param [a, b]
     * @Return double
     **/
    public static double add(Double a, Double b) {
        if (a == null || b == null) {
            return 0;
        }
        // 首先将整数转换为 BigDecimal 类型
        BigDecimal numerator = new BigDecimal(a.toString());
        BigDecimal denominator = new BigDecimal(b.toString());

        // 使用 subtract() 方法进行减法运算
        BigDecimal result = numerator.add(denominator);

        // 将结果转换为 double 类型返回
        return result.doubleValue();
    }

    /**
     * @Description 格式化double值，保留2位小数
     * @Date 2024/8/22 17:16
     * @Author YWX
     * @Param [value]
     * @Return java.lang.String
     **/
    public static String formatDouble(double value) {
        // 创建一个DecimalFormat实例，指定格式
        DecimalFormat decimalFormat = new DecimalFormat("0.##");

        // 返回格式化后的字符串
        return decimalFormat.format(value);
    }

    //格式化double值，保留2位小数
    public static Double formatDouble2(double value) {
        // 创建一个DecimalFormat实例，指定格式
        DecimalFormat decimalFormat = new DecimalFormat("0.##");

        // 格式化double值
        String formattedValue = decimalFormat.format(value);

        // 返回格式化后的字符串
        return Double.parseDouble(formattedValue);
    }

    /**
     * @Description 支付宝登录结果解析
     * @Date 2024/8/30 0:09
     * @Author YWX
     * @Param [response]
     * @Return java.lang.String
     **/
    public static String getLoginResult(String response) {
        //1. 获取验签和解密所需要的参数
        Map<String, String> openapiResult = JSON.parseObject(response, new TypeReference<>() {
        }, Feature.OrderedField);

        String sign = openapiResult.get("sign");
        String content = openapiResult.get("response");
        //判断是否为加密内容
        boolean isDataEncrypted = !content.startsWith("{");
        boolean signCheckPass = false;
        //2. 验签
        String signType = "RSA2";
        String charset = "UTF-8";
        String encryptType = "AES";
        String signContent = content;
        String decryptKey = ConfigKey.decryptKey;//如果是加密的报文则需要在密文的前后添加双引号
        if (isDataEncrypted) {
            signContent = "\"" + signContent + "\"";
        }
        try {
            //signCheckPass = AlipaySignature.rsaCheck(signContent, sign, signVeriKey, charset, signType);
            String alipayPublicCertPath = ConfigKey.certPath + "alipayCertPublicKey_RSA2.crt";
            signCheckPass = AlipaySignature.rsaCertCheck(signContent, sign, alipayPublicCertPath, charset, signType);
        } catch (AlipayApiException e) {
            // 验签异常, 日志
        }
        if (!signCheckPass) {
            ToolUtils.log.error("验签失败");
            //验签不通过（异常或者报文被篡改），终止流程（不需要做解密）
            throw new ServiceException("验签失败");
        }
        //3. 解密
        String plainData;
        if (isDataEncrypted) {
            try {
                plainData = AlipayEncrypt.decryptContent(content, encryptType, decryptKey, charset);
            } catch (AlipayApiException e) {
                ToolUtils.log.error("解密异常:{}", e.getMessage());
                //解密异常, 记录日志
                throw new ServiceException("解密异常");
            }
        } else {
            plainData = content;
        }

        return plainData;
    }

    private static final AlipayClient alipayClient;

    static {
        try {
            alipayClient = AlipayConfig.getAlipayClient();
        } catch (AlipayApiException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @Description 根据授权码获取支付宝用户信息
     * @Date 2024/8/30 0:07
     * @Author YWX
     * @Param [authCode]
     * @Return java.lang.String[]
     **/
    public static String[] getUserInfo(String authCode) {
        String[] id_phone = new String[2];
        // 1. 创建AlipayClient

        try {
            // 2. 创建API请求
            AlipayUserInfoShareRequest request = new AlipayUserInfoShareRequest();
            //request.setAuthCode(authCode);

            // 3. 发送请求并获取响应
            AlipayUserInfoShareResponse response = ToolUtils.alipayClient.certificateExecute(request, authCode);

            // 4. 解析响应数据
            if (response.isSuccess()) {
                id_phone[0] = response.getUserId();
                id_phone[1] = response.getMobile();
            } else {
                // 处理错误
                ToolUtils.log.error("获取用户信息失败：{} - {}", response.getSubCode(), response.getSubMsg());
                throw new ServiceException("获取用户信息失败:" + response.getSubMsg());
            }
        } catch (AlipayApiException e) {
            ToolUtils.log.error("获取用户信息失败：{}", e.getMessage());
            throw new ServiceException("获取用户信息失败:" + e.getMessage());
        }
        return id_phone;
    }

    /**
     * @Description 根据授权码获取支付宝access_token 和 user_id (open_id)
     * @Date 2024/8/31 15:08
     * @Author YWX
     * @Param [authCode]
     * @Return java.lang.String[]
     **/
    public static String[] getUserIdAndToken(String authCode) {
        String[] id_token = new String[3];

        try {
            AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();

            // 设置请求参数
            request.setGrantType("authorization_code"); // 固定值
            request.setCode(authCode);
            // 发送请求
            AlipaySystemOauthTokenResponse response = ToolUtils.alipayClient.certificateExecute(request);

            if (response.isSuccess()) {
                // 获取 access_token 和 user_id (open_id)
                id_token[0] = response.getUserId();
                id_token[1] = response.getAccessToken();
                id_token[2] = response.getOpenId();
            } else {
                ToolUtils.log.error("获取 token 失败: {}", response.getMsg());
            }
            ToolUtils.log.info("获取 token 成功: user_id:{}, access_token:{}, open_id:{}", id_token[0], id_token[1], id_token[2]);
        } catch (AlipayApiException e) {
            ToolUtils.log.error("获取 token 失败：{}", e.getMessage());
            throw new ServiceException("获取 token 失败:" + e.getMessage());
        }
        return id_token;
    }

    /**
     * @Description 将字符串编码为 URL 参数，类似于 JavaScript 的 encodeURIComponent 方法
     * @Date 2024/9/6 23:55
     * @Author YWX
     * @Param [input]
     * @Return java.lang.String
     **/
    public static String encodeURLParameter(String input) {
        // 指定使用 UTF-8 编码

        return URLEncoder.encode(input, StandardCharsets.UTF_8)
                // 替换 %2F 为 / （因为 '/' 不需要编码）
                .replace("+", "%20") // 替换空格为 %20
                .replace("*", "%2A") // 替换星号为 %2A
                .replace("%7E", "~");
    }

    /**
     * @Description 计算两个 LocalDateTime 之间相差的天数
     * @Date 2024/9/7 16:10
     * @Author YWX
     * @Param [begin, end]
     * @Return int
     **/
    public static int getDaysBetween(LocalDateTime begin, LocalDateTime end) {
        if (begin.getSecond() == 59) {
            begin = begin.plusSeconds(1);
        }
        Integer days = ToolUtils.objToInteger(ChronoUnit.DAYS.between(begin, end));
        LocalTime localTime = end.toLocalTime();
        if (!begin.toLocalTime().equals(localTime) && !localTime.equals(java.time.LocalTime.MIDNIGHT)) {
            days++;
        }
        return days;
    }

    /**
     * @Description 获取两个日期之间相差的天数
     * @Date 2024/11/9 23:12
     * @Author YWX
     * @Param [begin, end]
     * @Return int
     **/
    public static int getDaysBetween2(LocalDateTime begin, String end) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate beginDate = begin.toLocalDate();
        LocalDate endDate = LocalDate.parse(end, formatter);
        return ToolUtils.objToInteger(ChronoUnit.DAYS.between(beginDate, endDate));
    }

    /**
     * @Description 计算两个 LocalDateTime 之间相差的小时数
     * @Date 2024/9/25 12:56
     * @Author YWX
     * @Param [begin, end]
     * @Return long
     **/
    public static long getHoursBetween(LocalDateTime begin, LocalDateTime end) {
        return ChronoUnit.HOURS.between(begin, end);
    }

    /**
     * @Description 获取指定日期的结束时间（23:59:59）
     * @Date 2024/9/7 17:57
     * @Author YWX
     * @Param [dateStr]
     * @Return java.time.LocalDateTime
     **/
    public static @NotNull LocalDateTime getEndDateTime(String dateStr) {
        LocalDate date = LocalDate.parse(dateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        //创建当天的结束时间（23:59:59）
        LocalTime endOfDay = LocalTime.of(23, 59, 59);
        //组合日期和时间
        return LocalDateTime.of(date, endOfDay);
    }

    /**
     * @Description 获取指定日期的开始时间（00:00:00）
     * @Date 2024/9/11 21:51
     * @Author YWX
     * @Param [dateStr]
     * @Return java.time.LocalDateTime
     **/
    public static @NotNull LocalDateTime getBeginDateTime(String dateStr) {
        LocalDate date = LocalDate.parse(dateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        //创建当天的开始时间（00:00:00）
        LocalTime endOfDay = LocalTime.of(00, 00, 00);
        //组合日期和时间
        return LocalDateTime.of(date, endOfDay);
    }

    /**
     * @Description 字符串转 LocalDateTime
     * @Date 2024/9/30 9:05
     * @Author YWX
     * @Param [dateStr]
     * @Return java.time.LocalDateTime
     **/
    public static @NotNull LocalDateTime strToDateTime(String dateStr) {
        if (ToolUtils.isEmpty(dateStr)) {
            return null;
        }
        return LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
    }

    //时间戳转 LocalDateTime
    public static LocalDateTime timestampToDateTime(String timestamp) {
        if (ToolUtils.isEmpty(timestamp)) {
            return null;
        }
        return Instant.ofEpochMilli(objToLong(timestamp))
                .atZone(ZoneId.systemDefault()) // 使用系统默认时区
                .toLocalDateTime();
    }

    /**
     * @Description 去除字符串中的空格、换行符、制表符
     * @Date 2024/9/14 23:59
     * @Author YWX
     * @Param [str]
     * @Return java.lang.String
     **/
    public static String replaceMultipleSpaces(String str) {
        // 使用正则表达式将两个或以上的空格替换为一个空格
        return str.replaceAll("\\s+", " ").trim();
    }

    /**
     * @Description 字符串不足指定位数左右补空格
     * @Date 2024/10/15 14:11
     * @Author YWX
     * @Param [input, targetLength]
     * @Return java.lang.String
     **/
    public static String padString(String input, int targetLength) {
        // 计算当前字符串的长度（以汉字为单位）
        int currentLength = input.length();

        // 如果长度不足，计算需要补充的空格数量
        if (currentLength < targetLength) {
            // 计算需要补充的空格个数
            int totalPadding = targetLength - currentLength;
            int leftPadding = totalPadding / 2; // 左侧空格数量
            int rightPadding = totalPadding - leftPadding; // 右侧空格数量

            // 返回拼接后的字符串
            return " ".repeat(leftPadding) + input + " ".repeat(rightPadding);
        } else {
            // 如果当前字符串已经达到或超过目标长度，返回原字符串
            return input;
        }
    }

    /**
     * @Description 是否是白名单接口
     * @Date 2024/10/23 23:22
     * @Author YWX
     * @Param [requestURI, whitelistAPI]
     * @Return boolean
     **/
    public static boolean whiteAPI(String requestURI, String whitelistAPI) {
        boolean rtn = false;
        if (ToolUtils.isEmpty(whitelistAPI)) {
            return false;
        }
        String[] apis = whitelistAPI.split(",");
        for (String api : apis) {
            if (requestURI.contains(api)) {
                rtn = true;
                break;
            }
        }
        return rtn;
    }

    /**
     * @Description 获取请求头中的用户ID
     * @Date 2024/12/7 14:15
     * @Author YWX
     * @Param [request]
     * @Return java.lang.Integer
     **/
    public static Integer getHeaderUserId(HttpServletRequest request) {
        if (request == null) {
            return null;
        }
        try {
            return request.getIntHeader(GlobalConstant.USRID);
        } catch (Exception e) {
            return null;
        }
    }

    public static String getTypeByOrderType(Integer orderType) {
        String type = "RENT";
        if (orderType.equals(2)) {
            type = "BUYOUT";
        } else if (orderType.equals(3)) {
            type = "INDEMNITY";
        } else if (orderType.equals(4)) {
            type = "FREIGHT";
        }
        return type;
    }

    //base64解码
    public static String base64Decode(String str) {
        return new String(Base64.getDecoder().decode(str));
    }

    /**
     * @Description 格式化秒数为分钟和秒
     * @Date 2025/2/22 10:16
     * @Author YWX
     * @Param [seconds]
     * @Return java.lang.String
     **/
    public static String formatSeconds(Long seconds) {
        System.out.println("seconds:" + seconds);
        if (seconds < 60) {
            return seconds + "秒";
        } else {
            Long minutes = seconds / 60;
            Long remainingSeconds = seconds % 60;
            return minutes + "分钟" + remainingSeconds + "秒";
        }
    }

    /**
     * @Description 金额取整
     * @Date 2025/2/22 11:18
     * @Author YWX
     * @Param [value]
     * @Return int
     **/
    public static int truncate(Double value) {
        if (value == null) {
            return 0;
        }
        return value.intValue();
    }

}
